/*
	This file is part of "Ants on the web".

    "Ants on the web" is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    "Ants on the web" is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with "Ants on the web".  If not, see <http://www.gnu.org/licenses/>.
*/

package org.utc.ia04.antsontheweb.antColonyOptimisation.ant;

import java.net.MalformedURLException;
import java.net.URL;

import org.utc.ia04.antsontheweb.pheromone.PheromoneManagerAgent;
import org.utc.ia04.antsontheweb.utilities.PheromoneManagerMessage;
import org.utc.ia04.antsontheweb.utilities.Requete;
import org.utc.ia04.antsontheweb.utilities.RequeteException;

import jade.core.behaviours.CyclicBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;

public class AntBhv extends CyclicBehaviour
{
	//serialVersionUID
	private static final long serialVersionUID = -2967024063123902544L;

	public void action() 
	{
		ACLMessage receivedMsg = myAgent.receive();
		if( receivedMsg == null) block();
		else
		{
			// on parse pour savoir si on a affaire a une fourmis morte ou si des ressources collectees
			String msgContent =  receivedMsg.getContent();
			try
			{
				Requete query = Requete.deserialize_withException(msgContent, myAgent, receivedMsg);
				switch(query.getType())
				{
				case Requete.INC_TICK:
					((AntAgent)myAgent).incTickerTime();
					break;
				case Requete.AC_DEATH:
					myAgent.doDelete();
					block();
					break;
				case Requete.AC_GO :
					long ACtickerTime = Long.parseLong(query.getContent());
					if(desynchro(ACtickerTime))
					{
						//DEBUG
						System.out.println("DIE because of desynchro.");
						myAgent.doDelete();
						block();
					}
					if (((AntAgent)myAgent).getCarryRessource())
					{
						//Debug
						//System.out.println(myAgent.getName()+" is carrying ressource.");
						carryingRessource();
					}
					else
						{
							if (((AntAgent)myAgent).dropDead())
							{
								//DEBUG
								//System.out.println("Die of old Age.");
								myAgent.doDelete();
								block();
							}
							else
							{
								ACLMessage goMsg = new ACLMessage(ACLMessage.REQUEST);
								Requete goQuery = new Requete(Requete.ANT_GO, "");
								goMsg.setContent(goQuery.serialize());
								goMsg.addReceiver(((AntAgent)myAgent).getParserAID());
								myAgent.send(goMsg);
								//DEBUG
								//System.out.println("DEBUG: ant is sending a message to parser:" + goMsg.getContent());
							}
					}
					break;
				case Requete.ANTPARSER_RESSOURCEPICKUP:
					//DEBUG
					//System.out.println(myAgent.getName()+" recieve a message to carry ressource");
					//((AntAgent)myAgent).inverseVisitedUrlStack();
					//System.out.println(((AntAgent)myAgent).visitedUrl);
					
					((AntAgent)myAgent).setCarryRessource(true);
					//HACK TODO mieux decouper le code
					URL currentUrl = null, nextUrl = null;
					currentUrl = ((AntAgent)myAgent).visitedUrl.pop();
					if(!((AntAgent)myAgent).visitedUrl.isEmpty())
						nextUrl = ((AntAgent)myAgent).visitedUrl.peek();
					ACLMessage updatePhMsg = new ACLMessage(ACLMessage.REQUEST);
					PheromoneManagerMessage phMsg = new PheromoneManagerMessage(currentUrl,true,nextUrl,false);
					Requete updateQuery = new Requete(Requete.ANT_UPDATEPHEROMONE,phMsg.serialize());
					updatePhMsg.setContent(updateQuery.serialize());
					
					DFAgentDescription templatePhManager = new DFAgentDescription();
					ServiceDescription sdPh = new ServiceDescription();
					sdPh.setType(PheromoneManagerAgent.dfType); 
					templatePhManager.addServices(sdPh);
					try
					{
						DFAgentDescription[] result = DFService.search(myAgent, templatePhManager);
						for(int i = 0; i < result.length; ++i)
							updatePhMsg.addReceiver(result[i].getName());
					}
					catch(Exception fe) {System.out.println(fe.getMessage());}
					myAgent.send(updatePhMsg);
					//block();
					if (nextUrl == null)
					{
						//DEBUG
						System.out.println(myAgent.getName()+"finish to carry ressource");
						ACLMessage carryMsg = new ACLMessage(ACLMessage.INFORM);
						Requete pickupQuery = new Requete(Requete.ANT_RESSOURCEPICKUP,null);
						carryMsg.setContent(pickupQuery.serialize());
						carryMsg.addReceiver(((AntAgent)myAgent).getAntColonyAID());
						myAgent.send(carryMsg);
						myAgent.doDelete();
					}
					System.out.println("ANT BEGIN TO GO BACK set carry ressource has value: "+((AntAgent)myAgent).getCarryRessource());
					break;
				case Requete.ANTPATHFINDER_ASKHTMLCONTENT:
					//On ajoute une url visitee
					try
					{
						((AntAgent)myAgent).visitedUrl.push(new URL(query.getContent()));
					}
					catch (MalformedURLException e)
					{
						e.printStackTrace();
					}
					((AntAgent)myAgent).incAge();
					//DEBUG
					System.out.println("--------------------------------------");
					System.out.println(((AntAgent)myAgent).visitedUrl);
					System.out.println(myAgent.getName()+" receive a link tu push in its visitedURLS : " + query.getContent());
					System.out.println("--------------------------------------");

					break;
				default:
					System.out.println(myAgent.getName()+" received message from : " + receivedMsg.getSender() +  " => " + msgContent+" and not know how to treat it.");
					break;
						
			
				}
			}
			catch(RequeteException e) { }
		}

		
	}
	
	
	private void carryingRessource()
	{
		URL currentUrl = ((AntAgent)myAgent).visitedUrl.pop();
		if (((AntAgent)myAgent).visitedUrl.empty())
		{
			((AntAgent)myAgent).setCarryRessource(false);
			//DEBUG
			System.out.println(myAgent.getName()+"finish to carry ressource");
			ACLMessage carryMsg = new ACLMessage(ACLMessage.INFORM);
			Requete query = new Requete(Requete.ANT_RESSOURCEPICKUP,null);
			carryMsg.setContent(query.serialize());
			carryMsg.addReceiver(((AntAgent)myAgent).getAntColonyAID());
			myAgent.send(carryMsg);
			myAgent.doDelete();
		}
		else
		{
			
			URL nextUrl = ((AntAgent)myAgent).visitedUrl.peek();
			ACLMessage updatePhMsg = new ACLMessage(ACLMessage.REQUEST);
			PheromoneManagerMessage phMsg = new PheromoneManagerMessage(currentUrl,false,nextUrl,false);
			Requete query = new Requete(Requete.ANT_UPDATEPHEROMONE,phMsg.serialize());
			updatePhMsg.setContent(query.serialize());
			
			DFAgentDescription templatePhManager = new DFAgentDescription();
			ServiceDescription sdPh = new ServiceDescription();
			sdPh.setType(PheromoneManagerAgent.dfType); 
			templatePhManager.addServices(sdPh);
			try
			{
				DFAgentDescription[] result = DFService.search(myAgent, templatePhManager);
				for(int i = 0; i < result.length; ++i)
					updatePhMsg.addReceiver(result[i].getName());
			}
			catch(Exception fe) {System.out.println(fe.getMessage());}
			myAgent.send(updatePhMsg);
		}
	}



	private boolean desynchro(long parACTickerTime)
	{
		//TODO affiner la condition -> apprentissage?
		return (parACTickerTime == ((AntAgent)myAgent).getTickerTime());
	}
}